#pragma once

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
#include <functional>
#include <cstring>
#include <unordered_map>
#include "Log.hpp"
using namespace LOGSpace;
const static std::string base_sep = "\r\n";
const static std::string head_sep = ": ";
const static std::string prev_path = "RootHttp"; // web根目录
const static std::string Index_path = "index.html";
const static std::string HttpVersion = "HTTP/1.1";
const static std::string Space = " ";
const static std::string Error_path = "error.html";
const static std::string Redirect = "https://www.qq.com";
const static std::string ArgsSep = "?";
class Http_Request // HTTP请求
{

private:
    std::string DesStrFunc(std::string &reqstr)
    {
        // 1.找到第一个\r\n
        auto pos = reqstr.find(base_sep);
        if (pos == std::string::npos)
            return std::string();
        std::string line = reqstr.substr(0, pos);
        // 3.删除reqstr中的line
        reqstr.erase(0, line.size() + base_sep.size());
        return line.empty() ? base_sep : line;
    }

    void ParseReqLine(std::string &reqline)
    {
        std::stringstream ss(_reqline); // 以空格作为分隔符
        ss >> _method >> _url >> _version;

        // 判断method是什么方法
        if (strcasecmp(_method.c_str(), "GET") == 0)
        {
            auto pos = _url.find(ArgsSep);
            if (pos != std::string::npos)
            {
                _body_txt = _url.substr(pos + ArgsSep.size());
                _url.resize(pos);
            }
        }
        _path += _url;
        if (_path.back() == '/')
        {
            _path += Index_path;
        }
        auto pos = _path.rfind(".");
        if (pos == std::string::npos)
        {
            // 没找到后缀
            _suffix = ".default";
        }
        else
        {
            _suffix = _path.substr(pos);
        }
    }
    void parseHeads()
    {
        for (auto &head : _reqHeads)
        {
            auto pos = head.find(head_sep);
            if (pos == std::string::npos)
                continue;
            std::string head_key = head.substr(0, pos);
            std::string head_value = head.substr(pos + head_sep.size());
            if (head_key.empty() || head_value.empty())
                continue;
            _headers_map.insert(std::make_pair(head_key, head_value)); // 填充_headers_map;
        }
    }

public:
    Http_Request() : _null_line(base_sep), _path(prev_path)
    {
    }
    void Deserialization(std::string &reqstr)
    {
        _reqline = DesStrFunc(reqstr);

        std::string head;
        // 分割请求报头
        while (((head = DesStrFunc(reqstr)) != base_sep) && !head.empty())
        {
            _reqHeads.push_back(head);
        }
        // 提取正文
        if (!reqstr.empty())
        {
            _body_txt = reqstr;
        }
        ParseReqLine(_reqline);
        parseHeads(); // 填充_headers_map字段
    }
    std::string GetURL()
    {
        return _url;
    }
    std::string GetPath()
    {
        return _path;
    }
    std::string GetBodyText()
    {
        LOG(INFO, "request bodytext = %s\n", _body_txt.c_str());
        return _body_txt;
    }
    std::string GetSuffix()
    {
        return _suffix;
    }
    std::string GetMethod()
    {
        LOG(DEBUG, "get a client method = %s\n", _method.c_str());
        return _method;
    }
    void print()
    {
        std::cout << "-------------------------------" << std::endl;
        std::cout << "###" << _reqline << std::endl;
        for (auto &head : _reqHeads)
        {
            std::cout << "@@@" << head << std::endl;
        }
        std::cout << "***" << _null_line;
        std::cout << ">>>" << _body_txt << std::endl;
        std::cout << "-------------------------------" << std::endl;
        std::cout << "method: " << _method << std::endl;
        std::cout << "url: " << _url << std::endl;
        std::cout << "version: " << _version << std::endl;
        std::cout << "-------------------------------" << std::endl;
        for (auto &[k, v] : _headers_map)
        {
            std::cout << k << ": " << v << std::endl;
        }
    }

    ~Http_Request()
    {
    }

private:
    // 基本HTTP字段
    std::string _reqline;
    std::vector<std::string> _reqHeads;
    std::string _null_line;
    std::string _body_txt;
    std::string _suffix; // 发送回的数据的后缀类型
    // 进一步描述HTTP的字段
    std::string _method; // 请求方法
    std::string _url;    // 资源的绝对路径
    std::string _path;
    std::string _version;                                      // 版本
    std::unordered_map<std::string, std::string> _headers_map; // kv格式
};

class Http_Resp // HTTP响应
{
public:
    Http_Resp() : _httpversion(HttpVersion), _null_line(base_sep)
    {
    }
    void AddCode(int code, const std::string &status)
    {
        _status_code = code;
        _desc = status;
    }
    // 增加响应报头
    void AddHeads(const std::string &Key, const std::string &Value) // content_lenth : size
    {
        _heads_Map[Key] = Value; // 如果key存在则更改value
    }
    // 增加正文
    void AddBodyText(const std::string &text)
    {
        _body_txt = text;
    }
    // 序列化
    std::string Serialization()
    {
        // 填充状态行
        _StatusLine = _httpversion + Space + std::to_string(_status_code) + Space + _desc + base_sep;
        // 填充响应报头
        for (auto &[k, v] : _heads_Map)
        {
            std::string head_line = k + head_sep + v + base_sep;
            _resHeads.push_back(head_line);
        }
        std::string RespenceStr = _StatusLine;
        for (auto &head : _resHeads)
        {
            RespenceStr += head;
        }
        RespenceStr += _null_line;
        RespenceStr += _body_txt;
        return RespenceStr;
    }
    ~Http_Resp()
    {
    }

private:
    std::string _httpversion;
    int _status_code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _heads_Map;
    std::unordered_map<std::string, std::string> _content_type;

    //-------http响应的基本信息-----------
    std::string _StatusLine; // 响应状态行
    std::vector<std::string> _resHeads;
    std::string _null_line;
    std::string _body_txt; // 正文
    //---------------------------------
};

using func_t = std::function<Http_Resp(Http_Request &)>;

class http_service
{
private:
    std::string GetFileConten(const std::string &path)
    {
        // 读取指定路径下的内容
        // 二进制读取!!!
        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
            return std::string();
        // 将偏移量初始化到文件结尾
        in.seekg(0, in.end);
        // 获取文件的大小
        int filesize = in.tellg();
        // 将偏移量重置到开始位置
        in.seekg(0, in.beg);
        std::string resqstr;
        resqstr.resize(filesize);
        in.read((char *)resqstr.c_str(), resqstr.size());
        in.close();
        return resqstr;
    }

public:
    http_service()
    {
        // content-types
        _content_type.insert(std::make_pair(".html", "text/html"));
        _content_type.insert(std::make_pair(".png", "image/*"));
        _content_type.insert(std::make_pair(".jpg", "image/*"));
        _content_type.insert(std::make_pair(".mp4", "video/*"));
        _content_type.insert(std::make_pair(".txt", "text/plain"));
        _content_type.insert(std::make_pair(".default", "text/plain"));

        // Http状态码
        _codeToStatus_Map.insert(std::make_pair(100, "Continue"));
        _codeToStatus_Map.insert(std::make_pair(200, "OK"));
        _codeToStatus_Map.insert(std::make_pair(404, "Not Found"));
        _codeToStatus_Map.insert(std::make_pair(500, "Internal Server Error"));
        _codeToStatus_Map.insert(std::make_pair(302, "Found"));
    }
    ~http_service() {}
    std::string HanderHttpService(std::string requeststr)
    {
#ifdef TEST_HTTP
        std::cout << "---------------" << std::endl;
        std::cout << requeststr;
        std::string respence = "HTTP/1.1 200 ok\r\n";
        respence += "content-Type:text/html\r\n";
        respence += "\r\n";
        respence += "<html><h2>Virtual meeting room for members of the Software Association</h2></html>";
        return respence;
#else
        Http_Request rq;
        rq.Deserialization(requeststr);
        std::string content = GetFileConten(rq.GetPath());
        Http_Resp resp;
        rq.GetMethod();
        rq.GetBodyText();
        if (rq.GetPath() == "RootHttp/root")
        {
            resp.AddCode(302, _codeToStatus_Map[302]);
            resp.AddHeads("Location", Redirect);
        }
        else if(!rq.GetBodyText().empty())
        {
            //处理
            if(IsServiceExists(rq.GetPath()))
            {
              resp = _servicelists[rq.GetPath()](rq); 
            }
        }
        else
        {
            if (content.empty())
            {
                resp.AddCode(404, _codeToStatus_Map[404]);
                content = GetFileConten("RootHttp/error.html"); // 重新获取一次404的资源
                // 如果请求的资源不存在，就返回错误码
                resp.AddHeads("Content-Length", std::to_string(content.size()));
                resp.AddHeads("Content-Type", _content_type[".html"]);
                resp.AddBodyText(content);
            }
            else
            {
                // 成功读取index.html
                resp.AddCode(200, _codeToStatus_Map[200]);
                resp.AddHeads("Content-Length", std::to_string(content.size()));
                resp.AddHeads("Content-Type", _content_type[rq.GetSuffix()]);
                resp.AddBodyText(content);
            }
        }
        return resp.Serialization();
#endif
    }
    void InsertService(const std::string &servicename, func_t func)
    {
        std::string Allname = prev_path + servicename;
        _servicelists[Allname] = func;
    }
    //判断服务是否存在
    bool IsServiceExists(const std::string &servicename)
    {
        auto iter = _servicelists.find(servicename);
        if(iter == _servicelists.end()) return false;
        return true;
    }
private:
    std::unordered_map<std::string, std::string> _content_type;
    std::unordered_map<int, std::string> _codeToStatus_Map;
    std::unordered_map<std::string, func_t> _servicelists; // 注册的服务列表
};
